using System;
using System.Collections;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

namespace JEngine.Framework
{
    public static class UIExtend
    {
        #region ScrollRect指定位置

        /// <summary>
        /// 该方法不适用于无限循环列表
        /// </summary>
        /// <param name="scrollRect"></param>
        /// <param name="index">0开始的索引位置</param>
        /// <param name="duration">滑动时间</param>
        public static void MoveIndex(this ScrollRect scrollRect, int index, float duration = .3f)
        {
            RectTransform viewport = scrollRect.transform.GetChild(0).GetComponent<RectTransform>();
            RectTransform content = viewport.transform.GetChild(0).GetComponent<RectTransform>();


            RectTransform item = GetItem(index, content);
            Vector3 itemCurrentLocalPostion = scrollRect.GetComponent<RectTransform>()
                .InverseTransformVector(ConvertLocalPosToWorldPos(item));
            Vector3 itemTargetLocalPos = scrollRect.GetComponent<RectTransform>()
                .InverseTransformVector(ConvertLocalPosToWorldPos(viewport));

            Vector3 diff = itemTargetLocalPos - itemCurrentLocalPostion;
            diff.z = 0.0f;

            var newNormalizedPosition = new Vector2(
                diff.x / (content.GetComponent<RectTransform>().rect.width - viewport.rect.width),
                diff.y / (content.GetComponent<RectTransform>().rect.height - viewport.rect.height)
            );

            newNormalizedPosition = scrollRect.GetComponent<ScrollRect>().normalizedPosition - newNormalizedPosition;

            newNormalizedPosition.x = Mathf.Clamp01(newNormalizedPosition.x);
            newNormalizedPosition.y = Mathf.Clamp01(newNormalizedPosition.y);

            
            scrollRect.StartCoroutine(ScrollToPosition(newNormalizedPosition, duration, scrollRect));
        }

        private static RectTransform GetItem(int index, Transform content)
        {
            if (index < 0)
                Debug.LogError("日尼玛,你去拼个-1的Item  傻逼");
            if (index > content.transform.childCount)
                Debug.LogError("日尼玛,报错了撒,自己有几个item自己不晓得?去卖炸土豆算了");
            return content.transform.GetChild(index).GetComponent<RectTransform>();
        }

        private static IEnumerator ScrollToPosition(Vector2 targetPosition, float duration, ScrollRect scrollRect)
        {
            Vector2 startingPosition = scrollRect.normalizedPosition;
            float elapsedTime = 0f;

            while (elapsedTime < duration)
            {
                // 在duration时间内不断更新normalizedPosition的值
                scrollRect.normalizedPosition = Vector2.Lerp(startingPosition, targetPosition, elapsedTime / duration);
                elapsedTime += Time.deltaTime;
                yield return null; // 暂停并等待下一帧
            }

            // 确保最后一帧时normalizedPosition恰好等于目标位置
            scrollRect.normalizedPosition = targetPosition;
        }

        private static Vector3 ConvertLocalPosToWorldPos(RectTransform target)
        {
            var pivotOffset = new Vector3(
                (0.5f - target.pivot.x) * target.rect.size.x,
                (0.5f - target.pivot.y) * target.rect.size.y,
                0f);

            var localPosition = target.localPosition + pivotOffset;

            return target.parent.TransformPoint(localPosition);
        }

        #endregion
        /// <summary>
        /// 是否显示中
        /// </summary>
        /// <param name="canvas"></param>
        /// <returns></returns>
        public static bool IsShow(this Canvas canvas)
        {
            return canvas.gameObject.layer == LayerMask.NameToLayer("UI");
        }

        /// <summary>
        /// 通过设置Canvas的层级显示，代替gameObject.SetActive(true);
        /// </summary>
        /// <param name="canvas"></param>
        public static void ShowByCanvas(this Canvas canvas)
        {
            if (canvas.IsShow()) return;
            canvas.gameObject.SetLayer("UI");
        }
        /// <summary>
        /// 设置层级
        /// </summary>
        /// <param name="gameObj"></param>
        /// <param name="layerName"></param>
        public static void SetLayer(this GameObject gameObj, string layerName)
        {
            Debug.Log("layer:" + layerName);
            Transform[] trans = gameObj.transform.GetComponentsInChildren<Transform>(true);
            for (int i = 0; i < trans.Length; i++)
            {
                trans[i].gameObject.layer = LayerMask.NameToLayer(layerName);
            }
        }

        /// <summary>
        /// 通过设置Canvas的层级隐藏，代替gameObject.SetActive(false);
        /// </summary>
        /// <param name="canvas"></param>
        public static void HideByCanvas(this Canvas canvas)
        {
            if (!canvas.IsShow()) return;
            canvas.gameObject.SetLayer("UIHide");

        }
        public static void CanvasRescet(this Canvas canvas)
        {
            var rt = canvas.GetComponent<RectTransform>();
            rt.anchorMin = Vector2.zero;
            rt.anchorMax = Vector2.one;
            rt.anchoredPosition = Vector2.zero;
            rt.sizeDelta = Vector2.zero;
        }

        public static void AddListenerRiNiMa(this Button btn, Action back)
        {
            if (btn == null)
                return;
            
            btn.onClick.RemoveAllListeners();
            
            btn.onClick.AddListener(()=>
            {
                back.Invoke();
            });
        }

        /// <summary>
        /// 超框显示...
        /// </summary>
        /// <param name="textComponent"></param>
        /// <param name="value"></param>
        public static void SetTextWithEllipsis(this Text textComponent, string value)
        {
            var generator = new TextGenerator();
            var rectTransform = textComponent.GetComponent<RectTransform>();
            var settings = textComponent.GetGenerationSettings(rectTransform.rect.size);
            generator.Populate(value, settings);
            var characterCountVisible = generator.characterCountVisible;
            var updatedText = value;
            if (value.Length > characterCountVisible)
            {
                updatedText = value.Substring(0, characterCountVisible - 1);
                updatedText += "…";
            }

            textComponent.text = updatedText;
        }

        public delegate void ButtonClickCallback<T>(T arg1);

        /// <summary>
        /// 给button添加回调  解决同一个引用会覆盖的问题
        /// </summary>
        /// <param name="btn"></param>
        /// <param name="callback"></param>
        public static void AddClick(this Button btn, ButtonClickCallback<GameObject> callback)
        {
            btn.onClick.AddListener((() => { callback(EventSystem.current.currentSelectedGameObject); }));
        }

        public static void SetActive(this UIBehaviour ui, bool active)
        {
            ui.gameObject.SetActive(active);
        }

        /// <summary>
        /// 给button的 text组件赋值
        /// </summary>
        /// <param name="btn"></param>
        /// <param name="txt"></param>
        public static void SetText(this Button btn, string txt)
        {
            btn.transform.GetComponentInChildren<Text>().text = txt;
        }

        /// <summary>
        /// Texture 转 Texture2D
        /// </summary>
        /// <returns></returns>
        public static Texture2D ToTexture2D(this Texture texture)
        {
            Texture2D texture2D = new Texture2D(texture.width, texture.height, TextureFormat.RGBA32, false);
            RenderTexture currentRT = RenderTexture.active;
            RenderTexture renderTexture = RenderTexture.GetTemporary(texture.width, texture.height, 32);
            Graphics.Blit(texture, renderTexture);
            RenderTexture.active = renderTexture;
            texture2D.ReadPixels(new Rect(0, 0, renderTexture.width, renderTexture.height), 0, 0);
            texture2D.Apply();
            RenderTexture.active = currentRT;
            RenderTexture.ReleaseTemporary(renderTexture);
            return texture2D;
        }

        /// <summary>
        /// 剪裁图片
        /// </summary>
        /// <param name="sourceTexture">图片</param>
        /// <param name="cropWidth">剪裁比例宽度 比如剪裁更小  就是0.25f</param>
        /// <param name="cropHeight">剪裁比例高度 比如剪裁更小  就是0.25f</param>
        /// <returns></returns>
        public static Texture2D Crop(this Texture2D sourceTexture, float cropWidth = 0.25f, float cropHeight = 0.25f)
        {
            Rect cropRect = new Rect(0.42f, 0.42f, cropWidth, cropHeight);

            Rect sourceRect = new Rect(0, 0, sourceTexture.width, sourceTexture.height);
            // 创建一个新的Texture2D，用于存储裁剪后的图像
            Texture2D croppedTexture = new Texture2D((int) (sourceTexture.width * cropRect.width),
                (int) (sourceTexture.height * cropRect.height));

            // 计算裁剪后的图像的坐标和大小
            int x = (int) (sourceRect.width * cropRect.x);
            int y = (int) (sourceRect.height * cropRect.y);
            int width = (int) (sourceRect.width * cropRect.width);
            int height = (int) (sourceRect.height * cropRect.height);

            // 裁剪源图像，将结果存储到新的Texture2D中
            croppedTexture.SetPixels(sourceTexture.GetPixels(x, y, width, height));
            croppedTexture.Apply();

            return croppedTexture;
        }

        public static void OpenAutoSize(this InputField inputField, float minHeight, float maxHeight)
        {
            RectTransform rectTransform = inputField.GetComponent<RectTransform>();
            Text textComponent = inputField.textComponent;
            TextGenerator textGenerator = new TextGenerator();
            inputField.onValueChanged.AddListener((text) =>
            {
                Audio(minHeight, maxHeight, textComponent, textGenerator, text, rectTransform);
            });
        }

        private static void Audio(float minHeight, float maxHeight, Text textComponent, TextGenerator textGenerator,
            string text, RectTransform rectTransform)
        {
            var generationSettings = textComponent.GetGenerationSettings(textComponent.rectTransform.rect.size);
            float preferredHeight = textGenerator.GetPreferredHeight(text, generationSettings);
            preferredHeight = Mathf.Max(minHeight, preferredHeight);
            preferredHeight = Mathf.Min(maxHeight, preferredHeight);
            Vector2 sizeDelta = rectTransform.sizeDelta;
            sizeDelta.y = preferredHeight;
            rectTransform.sizeDelta = sizeDelta;
        }
    }
}